package com.liy.supercloud.ssoserver.controller;

import com.liy.cloud.system.entity.SysAccountEntity;
import com.liy.framework.common.annotation.IgnoreUserToken;
import com.liy.framework.common.exception.NotAuthorizationException;
import com.liy.framework.common.extvo.LoginInfo;
import com.liy.framework.common.extvo.ResultVO;
import com.liy.framework.common.extvo.RoleVo;
import com.liy.framework.common.extvo.StationRolesVo;
import com.liy.framework.common.extvo.TokenVo;
import com.liy.framework.common.extvo.UserStationRoleVo;
import com.liy.framework.common.redis.utils.RedisKeyUtils;
import com.liy.framework.common.redis.utils.RedisUtils;
import com.liy.framework.common.utils.DateUtil;
import com.liy.framework.common.utils.JSONUtils;
import com.liy.framework.common.utils.Tools;
import com.liy.framework.common.webmsg.WebMessage;
import com.liy.framework.web.spring.controller.SupportController;
import com.liy.framework.web.spring.utils.WebTools;
import com.liy.supercloud.ssoserver.config.GlobalVariable;
import com.liy.supercloud.ssoserver.config.JwtTokenSevice;
import com.liy.supercloud.ssoserver.feign.SystemFeignClient;
import com.liy.supercloud.ssoserver.feign.WebMessageClient;
import com.liy.supercloud.ssoserver.service.UserResourcesService;
import com.liy.supercloud.ssoserver.vo.SysLoginLog;
import com.fasterxml.jackson.core.type.TypeReference;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;

import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping({"/auth/security"})
public class UserLoginController extends SupportController {

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private GlobalVariable globalVariable;

    @Autowired
    private JwtTokenSevice jwtTokenUtil;

    @Autowired
    private UserResourcesService userResourcesService;

    @Autowired
    private SystemFeignClient systemFeignClient;

    @Autowired
    private WebMessageClient webMessageClient;

    @Value("${dascloud.authrization.token.expire:1800}")
    private long expire;

    @Value("${dascloud.authrization.token.refresh: 3000}")
    private long refresh;

    @Value("${dascloud.authrization.token.client-count: 1}")
    private Integer clientCount;



    @RequestMapping(
            value = {"/login"},
            method = {RequestMethod.POST}
    )
    @ResponseBody
    @IgnoreUserToken
    public ResultVO login(@RequestBody SysAccountEntity entity) throws Exception {
        ResultVO result = new ResultVO();
        String loginIp = WebTools.getRequestIp(this.request);
        String userAgent = this.request.getHeader("User-Agent");
        if (!Tools.StringIsNullOrSpace(entity.getAccount()) && !Tools.StringIsNullOrSpace(entity.getPassword())) {
            SysLoginLog loginLog = new SysLoginLog();
            loginLog.setAccount(entity.getAccount());
            loginLog.setPassword(entity.getPassword());
            loginLog.setLogindate(DateUtil.getTimeNow());
            loginLog.setLoginClient(userAgent);
            loginLog.setLoginip(loginIp);
            ResultVO resultObj = this.systemFeignClient.queryUserByAccount(entity.getAccount());
            if (resultObj.isSuccess() && resultObj.getData() != null) {
                SysAccountEntity accountEntity = JSONUtils.json2Object(JSONUtils.object2Json(resultObj.getData()), SysAccountEntity.class);
                String dbpwd = DigestUtils.md5Hex(entity.getPassword().trim());
                if (!dbpwd.equals(accountEntity.getPassword())) {
                    result.setSuccess(false);
                    result.setMessage("用户名或密码错误.");
                    log.info("用户" + entity.getAccount() + "登录失败：" + result.getMessage());
                    loginLog.setLoginflag("1");
                    loginLog.setRemark("用户名或密码错误.");
                    this.saveLoginLog(loginLog);
                    return result;
                } else if (!"1".equals(accountEntity.getStatus())) {
                    result.setSuccess(false);
                    result.setMessage("用户账号已被注销或禁用，请联系管理员.");
                    log.info("用户" + entity.getAccount() + "登录失败：" + result.getMessage());
                    loginLog.setLoginflag("1");
                    loginLog.setRemark("用户账号已被注销或禁用，请联系管理员.");
                    this.saveLoginLog(loginLog);
                    return result;
                } else {
                    List<StationRolesVo> myStationRoles = this.getUserStationRolesList(accountEntity.getAccount());
                    String tokenId = RedisKeyUtils.getTokenKey((String)accountEntity.getId());
                    TokenVo token = new TokenVo((String)accountEntity.getId(), loginIp, System.currentTimeMillis());
                    token.setAccount(accountEntity.getAccount());
                    token.setName(accountEntity.getName());
                    token.setLoginTime(System.currentTimeMillis());
                    token.setLastOperationTime(System.currentTimeMillis());
                    token.setUserAgent(userAgent);
                    token.setStationRoles(myStationRoles);
                    token.setStatus(0);
                    LoginInfo loginInfo = new LoginInfo();
                    loginInfo.setId((String)accountEntity.getId());
                    loginInfo.setAccount(accountEntity.getAccount());
                    loginInfo.setName(accountEntity.getName());
                    loginInfo.setLoginIp(loginIp);
                    if ("adminx".equals(accountEntity.getAccount())) {
                        loginInfo.setUserType("SA");
                    } else {
                        loginInfo.setUserType("U");
                    }

                    loginInfo.setStationRoles(myStationRoles);
                    String jwtToken = this.jwtTokenUtil.generateToken(loginInfo);
                    token.setJwt(jwtToken);
                    this.redisUtils.set(tokenId, token, this.expire);
                    this.userResourcesService.saveUserPermissionToRedis((String)accountEntity.getId());
                    result.put("token", RedisKeyUtils.tokenId2base64(tokenId));
                    result.put("userInfo", loginInfo);
                    this.clientLoginCountCheck(loginIp, tokenId, (String)accountEntity.getId());
                    loginLog.setLoginflag("0");
                    loginLog.setRemark("登录成功");
                    this.saveLoginLog(loginLog);
                    log.info("用户:" + accountEntity.getAccount() + "登录成功,Token:" + tokenId + ", ip:" + loginIp + ", userAgent:" + userAgent);
                    return result;
                }
            } else {
                result.setSuccess(false);
                result.setMessage("用户不存在或已被删除.");
                log.info("用户" + entity.getAccount() + "登录失败：" + result.getMessage());
                loginLog.setLoginflag("1");
                loginLog.setRemark("用户不存在或已被删除.");
                this.saveLoginLog(loginLog);
                return result;
            }
        } else {
            result.setSuccess(false);
            result.setMessage("请求参数不完整");
            return result;
        }
    }


    private String getUserStationRoles(String userId) throws Exception, IOException {
        ResultVO result = this.systemFeignClient.queryUserRoleStation(userId);
        if (result.getData() != null && !Tools.StringIsNullOrSpace(result.getData().toString())) {
            String json = JSONUtils.object2Json(result.getData());

            List<UserStationRoleVo> list = (List<UserStationRoleVo>) JSONUtils.json2List(json, new TypeReference<List<UserStationRoleVo>>() {});

            Map<String, Object> map = new HashMap();
            Iterator var6 = list.iterator();

            while(var6.hasNext()) {
                UserStationRoleVo stationRoleVo = (UserStationRoleVo)var6.next();
                map.put(stationRoleVo.getStationId(), stationRoleVo.getStationName());
            }

            StringBuilder sr = new StringBuilder();
            Iterator var13 = map.keySet().iterator();

            while(var13.hasNext()) {
                String key = (String)var13.next();
                StringBuilder roles = new StringBuilder();
                Iterator var10 = list.iterator();

                while(var10.hasNext()) {
                    UserStationRoleVo stationRoleVo = (UserStationRoleVo)var10.next();
                    roles.append(stationRoleVo.getRoleId()).append(":").append(stationRoleVo.getRoleName()).append(",");
                }

                sr.append(key).append(":").append(map.get(key)).append("@").append(roles.toString().substring(0, roles.toString().length() - 1)).append(";");
            }

            return sr.toString();
        } else {
            return "";
        }
    }



    private List<StationRolesVo> getUserStationRolesList(String userId) throws Exception, IOException {

        ResultVO result = this.systemFeignClient.queryUserRoleStation(userId);

        List<StationRolesVo> resultList = new ArrayList();
        if (result.getData() != null && !Tools.StringIsNullOrSpace(result.getData().toString())) {
            String json = JSONUtils.object2Json(result.getData());

            List<UserStationRoleVo> list = (List<UserStationRoleVo>) JSONUtils.json2List(json, new TypeReference<List<UserStationRoleVo>>() {});

            Map<String, Object> map = new HashMap();
            Iterator var7 = list.iterator();

            while(var7.hasNext()) {
                UserStationRoleVo stationRoleVo = (UserStationRoleVo)var7.next();
                map.put(stationRoleVo.getStationId(), stationRoleVo.getStationName());
            }

            var7 = map.keySet().iterator();

            while(var7.hasNext()) {
                String key = (String)var7.next();
                List<RoleVo> tmpList = new ArrayList();
                Iterator var10 = list.iterator();

                while(var10.hasNext()) {
                    UserStationRoleVo vo = (UserStationRoleVo)var10.next();
                    if (key.equals(vo.getStationId())) {
                        tmpList.add(new RoleVo(vo.getRoleId(), vo.getRoleName()));
                    }
                }

                resultList.add(new StationRolesVo(key, map.get(key).toString(), tmpList));
            }
        }

        return resultList;
    }

    private void saveLoginLog(SysLoginLog loginLog) {
        try {
            ResultVO result = this.systemFeignClient.addLoginLog(loginLog);
            log.info(loginLog.getAccount() + ":" + loginLog.getRemark() + ", 日志保存：" + result.isSuccess() + ":" + result.getMessage());
        } catch (Exception var3) {
            log.info(loginLog.getAccount() + "登录日志保存失败: " + var3.getMessage(), var3);
        }

    }

    private void clientLoginCountCheck(String loginIp, String tokenId, String userId) {
        try {
            if (this.clientCount <= 0) {
                this.clientCount = 1;
            }

            LinkedHashSet<String> arr = (LinkedHashSet)this.redisUtils.gets(RedisKeyUtils.getTokenKeyPrefix(userId) + "*");
            if (arr != null && arr.size() > 1) {
                if (arr.size() <= this.clientCount) {
                    return;
                }

                arr.remove(tokenId);
                int rmCount = 0;
                Iterator var6 = arr.iterator();

                while(var6.hasNext()) {
                    String key = (String)var6.next();
                    if (rmCount >= arr.size() - this.clientCount) {
                        return;
                    }

                    TokenVo tokenVo = (TokenVo)this.redisUtils.get(key);
                    if (tokenVo != null) {
                        tokenVo.setStatus(2);
                    }

                    this.redisUtils.set(key, tokenVo, 60L);
                    ++rmCount;
                    this.sendOffLineMsg(loginIp, key);
                }
            }
        } catch (Exception var9) {
            log.error("在线用户检测时发生错误：" + var9.getMessage(), var9);
        }

    }

    private void sendOffLineMsg(String loginIp, String key) {
        try {
            WebMessage message = new WebMessage();
            message.setBid(key);
            message.setTitle("下线通知");
            message.setType("03");
            message.setContents("您的账号在" + loginIp + "登录，您已被迫下线，如非本人操作请及时联系管理员!");
            ResultVO resultVO = this.webMessageClient.sendClient(message, key);
            log.warn("用户" + key + "被迫下线通知发送" + (resultVO.isSuccess() ? "成功" : "失败：" + resultVO.getMessage()));
        } catch (Exception var5) {
            log.info("用户" + key + "被迫下线通知发送错误：" + var5.getMessage(), var5);
        }

    }

    private void cacheUserMenu(String userId) {
    }

    @RequestMapping({"/logout"})
    @ResponseBody
    public ResultVO logout() throws NotAuthorizationException, UnsupportedEncodingException {
        ResultVO result = new ResultVO();
        String authorization = super.getAuthorization();
        if (Tools.StringIsNullOrSpace(authorization)) {
            result.setSuccess(false);
            result.setMessage("未找到请求的认证信息.");
            return result;
        } else {
            String tokenId = RedisKeyUtils.base642tokenId(authorization);
            String[] arr = tokenId.split(":");
            if (arr.length == 3) {
                this.redisUtils.remove(tokenId);
            }

            result.setSuccess(true);
            result.setMessage("注销成功");
            return result;
        }
    }
}
